
dojo.provide("simp.DragResizeRegion");
dojo.require("dijit._Widget");
dojo.require("dijit._Templated");
//dojo.require("dojo.math"); 

dojo.declare('simp.DragResizeRegion',
	[dijit._Widget, dijit._Templated],
	{
	// minHeight: Integer
	//	smallest height in px resized node can be
	minHeight: 50,

	// minWidth: Integer
	//	smallest width in px resize node can be
	minWidth: 50,
	
	// holdAspectRatio: bool
	// disable the resizehandles n, e, s, w
	holdAspectRatio: false,
	
	showHandles: true,
	
	// dragCornerHoldsAspectRatio
	cornerRefreshOnAspect: true,
	
	handleWidthOffset: 3,
	
	handleHeightOffset: 3,
	
	coords: {},
	
	bounds: {},
	
	templatePath: dojo.moduleUrl("simp","templates/DragResizeRegion.html"),
	
	// --- dev model --- //
	_refreshHandle: {},
	_stopRefreshHandle: {},
	
	_current: {},
	
	_offset: {},
	
	postCreate: function() {
		//dojo.connect(this.Region, "dblclick", "onDblClick");
		//dojo.connect(this.Region, "mousedown", "onMouseDown");
		if (this.containerNode.clientHeight > this.minHeight) {
			this.coords.w = this.containerNode.clientWidth;
			this.coords.h = this.containerNode.clientHeight;
			this.coords.t = (this.domNode.parentNode.clientHeight - this.coords.h) / 2
			this.coords.l = (this.domNode.parentNode.clientWidth - this.coords.w) / 2			
		} else  {
			this.coords.w = this.minWidth;
			this.coords.h = this.minHeight;
			this.coords.t = (this.domNode.parentNode.clientHeight - this.minHeight) / 2
			this.coords.l = (this.domNode.parentNode.clientWidth - this.minWidth) / 2
		}
		this.bounds = {t: 0, l: 0, w: this.domNode.parentNode.clientWidth, h: this.domNode.parentNode.clientHeight}
		
		this.setup();
	},
	
	setup: function() {
		
		if (this.holdAspectRatio) {
			this.cornerRefreshOnAspect = true;
			dojo.style(this.NHandle, 'display', "none");
			dojo.style(this.EHandle, 'display', "none");
			dojo.style(this.SHandle, 'display', "none");
			dojo.style(this.WHandle, 'display', "none");
		}	
		if (this.showHandles == false) {
			dojo.style(this.NWHandle, 'display', "none");
			dojo.style(this.NHandle, 'display', "none");
			dojo.style(this.NEHandle, 'display', "none");
			dojo.style(this.EHandle, 'display', "none");
			dojo.style(this.SEHandle, 'display', "none");
			dojo.style(this.SHandle, 'display', "none");
			dojo.style(this.SWHandle, 'display', "none");
			dojo.style(this.WHandle, 'display', "none");			
		}
		
		this.handleWidthOffset = this.NWHandle.scrollWidth / 2;
		this.handleHeightOffset = this.NWHandle.scrollHeight / 2;
		
		console.debug("DragResizeRegion this.bounds: " + dojo.debugReturn(this.bounds));
		
		dojo.style(this.domNode, 'width', this.coords.w + "px");
		dojo.style(this.domNode, 'height', this.coords.h + "px");
		dojo.style(this.domNode, 'top', this.bounds.t + (this.coords.t - this._offset.y) + "px");
		dojo.style(this.domNode, 'left', this.bounds.l + (this.coords.l - this._offset.x) + "px");
		
		this._offset = { 
			x: (this.domNode.scrollWidth - dojo.style(this.domNode, 'width')) / 2, 
			y: (this.domNode.scrollHeight - dojo.style(this.domNode, 'height')) / 2 };
		if (djConfig.isDebug)
			console.debug("set offsets to: x: "+this._offset.x+" y: "+this._offset.y);

		this._positionRegion();	
		this._positionHandles();
	},
	
	_onMouseDown: function(event) {
		dojo.stopEvent(event);
		var affected = "";
		switch(event.target) {
			case this.NWHandle: affected = "NW";
				break;
			case this.NHandle: affected = "N";
				break;
			case this.NEHandle: affected = "NE";
				break;
			case this.EHandle: affected = "E";
				break;
			case this.SEHandle: affected = "SE";
				break;
			case this.SHandle: affected = "S";
				break;
			case this.SWHandle: affected = "SW";
				break;
			case this.WHandle: affected = "W";
				break;		
			default: affected = "NESW";	
		}
		if (djConfig.isDebug)
			console.debug("actived affected: "+affected);
		if (affected != "") {
			//this._refreshHandle = dojo.connect(null, 'onmousemove', this, "_refreshOnAspect");
			this._refreshHandle = dojo.connect(null, "onmousemove",this, "_refresh");
			this._stopRefreshHandle = dojo.connect(null, "onmouseup", this, "_stopRefresh");
			this._current = { affected: affected, x: event.pageX, y: event.pageY, aspect: (this.coords.h / this.coords.w) }
		}
	},

	_refresh: function(event) {
		dojo.stopEvent(event);
		
		var xdiff = this._current.x - event.pageX;
		var ydiff = this._current.y - event.pageY;
		var diff = {
			x: xdiff,
			y: ydiff,
		}
		
		//console.debug("refresh with xdiff: " + xdiff);		//console.debug("refresh with ydiff: " + ydiff);
		
		var b = this.bounds;  
		var r = this.coords;
		
		var affected = this._current.affected; 
		var moving = (affected.length > 2) ? true : false;
		
		//console.debug("on refresh - affected: "+affected);
		if (this.cornerRefreshOnAspect && affected.length == 2)	{
			this._refreshOnAspect(diff, affected, r, b);
		}
		else {
			if( affected.indexOf("S") >= 0 ){
				if(!moving) {
					var newHeight = r.h - ydiff;
					if ( newHeight + r.t >= b.h ) newHeight = b.h - r.t - this._offset.y; // size south
					if ( newHeight < this.minHeight ) newHeight = this.minHeight; // South handles only
					//console.debug("set Region height to " + (newHeight));
					this.coords.h = newHeight;
				}
			}
			if( affected.indexOf("N") >= 0 ){
				if(!moving) {
					var newHeight = r.h + ydiff;
					if ( newHeight < this.minHeight) newHeight = this.minHeight;
					this.coords.h = newHeight
				}
				var newTop = 0;
				if( r.t - ydiff > b.t ) newTop = r.t - ydiff;
				if(r.h + r.t - ydiff >= b.h) newTop = b.h - r.h;
				this.coords.t = newTop
				//console.debug("set Regio top to " + rTop - ydiff);
			}
			if( affected.indexOf("E") >= 0 ){
				if(!moving) {
					newWidth = r.w - xdiff;
					if (r.l + newWidth > b.w + b.l) newWidth = b.w - r.l - this._offset.x;
					if (newWidth < this.minWidth) newWidth = this.minWidth;
					//console.debug("set Region width to " + newWidth);
					this.coords.w = newWidth;
				}
			}
			if( affected.indexOf("W") >= 0 ){
				var newLeft = 0;
				if (r.l - xdiff > 0) newLeft = r.l - xdiff;
				if ((newLeft + r.w) >= b.w) newLeft = b.w - r.w;
				//dojo.style(this.domNode, 'left', newLeft + "px"); 
				r.l = newLeft;
				this.coords.l = newLeft;
				if(!moving) {
					newWidth = r.w + xdiff;
					if (r.l + newWidth > b.w + b.l) newWidth = b.w - r.l;
					if (newWidth < this.minWidth) newWidth = this.minWidth;
					//console.debug("set Region width to " + (newWidth));
					this.coords.w = newWidth;
				}
			}
		}
		console.debug("Resized to: " + dojo.debugReturn(this.coords));
		this._positionRegion();
		this._positionHandles();	
		this._current.x = event.pageX;
		this._current.y = event.pageY;	
		this.onResize();
	},
	
	_refreshOnAspect: function(diff, affected, r, b) {
		console.debug("refresh on Aspect");
		switch (affected) {
			case 'NW':
				var w = {
					old: r.w,
					cur: r.w - diff.x
				}
				var h = {
					old: r.h,
					cur: r.h - diff.y
				}
				var factor = this._setDiffFactor(r, w, h)
				this.coords.t = r.t + (r.h - this.coords.h)
				this.coords.l = r.l + (r.w - this.coords.w)
				break;
			case 'NE':
				var w = {
					old: r.w,
					cur: r.w + diff.x
				}
				var h = {
					old: r.h,
					cur: r.h - diff.y
				}
				var factor = this._setDiffFactor(r, w, h)
				this.coords.t = r.t - (r.h - this.coords.h)
				break;
			case 'SE':
				var w = {
					old: r.w,
					cur: r.w + diff.x
				}
				var h = {
					old: r.h,
					cur: r.h + diff.y
				}
				var factor = this._setDiffFactor(r, w, h)
				break;
			case 'SW':
				var w = {
					old: r.w,
					cur: r.w - diff.x
				}
				var h = {
					old: r.h,
					cur: r.h + diff.y
				}
				var factor = this._setDiffFactor(r, w, h)	
				this.coords.l = r.l + (r.w - this.coords.w)
				break;
		}
		//this.coords.t = b.t - r.t;
		//this.coords.l = b.l - r.l;
	},
	
	_setDiffFactor: function (r, w, h) {
		wfactor = w.old / w.cur;
		hfactor = h.old / h.cur;
		console.debug ("found factors: x - "+wfactor+", y - "+hfactor);
		var factor = hfactor;
		if (wfactor >= hfactor)
			factor = wfactor;
		factor = (Math.round(factor * 1000) / 1000);
		console.debug("use factor: " + factor);
		var newWidth = r.w * factor;
		var newHeight = r.h * factor;
		if (newWidth < this.minWidth) {
			factor = x.old / this.minWidth;
			newWidth = r.w * factor;
			newHeight = r.h * factor;
		}
		if (newHeight < this.minHeight) {
			factor = y.old / this.minHeight;
			newHeight = r.h * factor;
			newWidth = r.w * factor;			
		}
		this.coords.w = newWidth
		this.coords.h = newHeight
		if (djConfig.isDebug)
			console.debug("aspect factor was used as: " + factor);
		return factor;
	},
	
	_positionRegion: function() {
		
		dojo.style(this.domNode, "top", this.bounds.t + (this.coords.t - this._offset.y) + "px");
		dojo.style(this.domNode, "left", this.bounds.l + (this.coords.l - this._offset.y) + "px");
		dojo.style(this.domNode, "width", this.coords.w + "px");
		dojo.style(this.domNode, "height", this.coords.h + "px");
	},
	
	_positionHandles: function() {
		
		if (this.holdAspectRatio) {
			this.cornerRefreshOnAspect = true;
			dojo.style(this.NHandle, 'display', "none");
			dojo.style(this.EHandle, 'display', "none");
			dojo.style(this.SHandle, 'display', "none");
			dojo.style(this.WHandle, 'display', "none");
		}

		var r = this.coords;
		var wOffset = this.handleWidthOffset; 
		var hOffset = this.handleHeightOffset;

		dojo.style(this.NHandle, 'left', r.w / 2 - wOffset + 'px');
		dojo.style(this.NHandle, 'top', - hOffset + 'px');

		dojo.style(this.NEHandle, 'left', r.w - wOffset + 'px');
		dojo.style(this.NEHandle, 'top', - hOffset + 'px');

		dojo.style(this.EHandle, 'left', r.w - wOffset + 'px');
		dojo.style(this.EHandle, 'top', r.h / 2 - hOffset + 'px');

		dojo.style(this.SEHandle, 'left', r.w - wOffset + 'px');
		dojo.style(this.SEHandle, 'top', r.h - hOffset + 'px');
		
		dojo.style(this.SHandle, 'left', r.w / 2 - wOffset + 'px');
		dojo.style(this.SHandle, 'top', r.h - hOffset + 'px');
		
		dojo.style(this.SWHandle, 'left', - wOffset + 'px');
		dojo.style(this.SWHandle, 'top', r.h - hOffset + 'px');
		
		dojo.style(this.WHandle, 'left',  - wOffset + 'px');
		dojo.style(this.WHandle, 'top', r.h / 2 - hOffset + 'px');

		dojo.style(this.NWHandle, 'left', - wOffset + 'px');
		dojo.style(this.NWHandle, 'top', - hOffset + 'px');	
	},
	
	_stopRefresh: function(event) {
		dojo.stopEvent(event);
		dojo.disconnect(this._refreshHandle);
		dojo.disconnect(this._stopRefreshHandle);	
		if (djConfig.isDebug)
			console.debug("stop refresh");	
		this.onCompleted();
	},
	
	_onDblClick: function(event) {
		dojo.stopEvent(event);
		console.debug("DragResizeRegion: Region Selected - top: " + this.coords.t + " left: " + this.coords.l + " height: " + this.coords.h + " width: " + this.coords.w)
		this.onRegionDblClick();
	},
	
	getCoords: function() {
		return this.coords;
	},
	
	setCoords: function(coords) {
		console.debug("setCoords to DragResizeRegion: " + dojo.debugReturn(coords));
		if (coords != null) {
			if (coords.t) 
				this.coords.t = coords.t;
			if (coords.l)
				this.coords.l = coords.l;
			if (coords.w)
				this.coords.w = coords.w;
			if (coords.h)
				this.coords.h = coords.h;
			this.setup();
		}
	},	
	
	getBounds: function() {
		console.debug("getBounds");
		return this.bounds;
	},
	
	setBounds: function(bounds) {
		console.debug("setBounds to DragResizeRegion: " + dojo.debugReturn(bounds));
		this.bounds = bounds;
		this.setup();
	},
	
	getOffset: function() {
		return this._offset;
	},
	
	// events
	onResize: function() {
		
	},
	
	onBegin: function() {
		
	},
	
	onCompleted: function () {
		
	},
	
	onRegionDblClick: function () {
		
	},
}
);
